//
//  SMTThingsManager.m
//  smarthings
//
//  Created by Stefan Tsvyatkov on 10/20/14.
//  Copyright (c) 2014 Stefan Tsvyatkov. All rights reserved.
//

#import "SMTThingsManager.h"
#import "SMTWebServiceManager.h"
#import "SMTThing.h"
#import "SMTThingProperty.h"
#import "SMTThingAction.h"
#import "NSDictionary+NSDictionary_GeneralThingsObject.h"

static NSArray * actionTypes;
static NSArray * propertyTypes;


@implementation SMTThingsManager


#pragma mark - Interface methods

- (void)getThingsList {
    [[SMTWebServiceManager sharedInstance]
     getThingPropertyTypesList:^(id response) {
         
         NSMutableArray * returnedPropertyTypes = [NSMutableArray new];
         for (NSDictionary * propertyTypeDict in [(NSDictionary *)response objectForKey:@"items"]) {
             SMTThingPropertyType * propertyType = [SMTThingPropertyType new];
             [propertyTypeDict populateObject:propertyType];
             propertyType.name = [propertyTypeDict objectForKey:@"description"];
             propertyType.uuid = [propertyType.href lastPathComponent];
             propertyType.min = [propertyTypeDict objectForKey:@"min"];
             propertyType.max = [propertyTypeDict objectForKey:@"max"];
             propertyType.valueType = [propertyTypeDict objectForKey:@"type"];
             propertyType.unit = [propertyTypeDict objectForKey:@"unit"];
             [returnedPropertyTypes addObject:propertyType];
         }
         propertyTypes = [NSArray arrayWithArray:returnedPropertyTypes];
         
         [[SMTWebServiceManager sharedInstance]
          getThingActionTypesList:^(id response) {
              
              NSMutableArray * returnedActionTypes = [NSMutableArray new];
              for (NSDictionary * actionTypeDict in [(NSDictionary *)response objectForKey:@"items"]) {
                  SMTThingActionType * actionType = [SMTThingActionType new];
                  [actionTypeDict populateObject:actionType];
                  actionType.name = [actionTypeDict objectForKey:@"description"];
                  actionType.uuid = [actionType.href lastPathComponent];
                  [returnedActionTypes addObject:actionType];
              }
              actionTypes = [NSArray arrayWithArray:returnedActionTypes];
              
              [[SMTWebServiceManager sharedInstance]
               getThingsList:^(id response){
                   NSMutableArray * things = [NSMutableArray new];
                   __block unsigned long remainingResponses = 0;
                   __block BOOL isFailed = NO;
                   
                   if (response[@"items"] == nil) {
                       if ([self.delegate respondsToSelector:@selector(getThingsListFinishedWithSuccess:)]) {
                           [self.delegate getThingsListFinishedWithSuccess:things];
                       }
                       return;
                   }
                   
                   for (NSDictionary * thingDict in response[@"items"]) {
                       __block SMTThing * thing = [SMTThing new];
                       [thingDict populateObject:thing];
                       thing.state = thingDict[@"state"];
                       
                       if (isFailed) {
                           break;
                       }
                       
                       if (thingDict[@"properties"]) {
                           remainingResponses ++;
                           [[SMTWebServiceManager sharedInstance]
                            getAttributesForHref:thingDict[@"properties"]
                            success:^(id response) {
                                NSMutableArray * properties = [NSMutableArray new];
                                for (NSDictionary * propertyDict in response[@"items"]) {
                                    SMTThingProperty * property = [SMTThingProperty new];
                                    [propertyDict populateObject:property];
                                    property.name = [propertyDict objectForKey:@"type"];
                                    property.subscribeURL = [propertyDict objectForKey:@"subscribe"];
                                    for (SMTThingPropertyType * propertyType in propertyTypes) {
                                        if ([propertyType.uuid isEqualToString:property.name]) {
                                            property.propertyType = propertyType;
                                            break;
                                        }
                                    }
                                    if (property.propertyType != nil) {
                                        [properties addObject:property];
                                    }
                                    else {
                                        NSLog(@"Property type %@ in thing %@ does not exist.", property.name, thing.name);
                                    }
                                }
                                thing.properties = properties;
                                remainingResponses --;
                                if (remainingResponses == 0 && !isFailed) {
                                    if ([self.delegate respondsToSelector:@selector(getThingsListFinishedWithSuccess:)]) {
                                        [self.delegate getThingsListFinishedWithSuccess:things];
                                    }
                                }
                            }
                            failure:^(NSError * error) {
                                if (!isFailed) {
                                    isFailed = YES;
                                    if ([self.delegate respondsToSelector:@selector(getThingsListFinishedWithFailure:)]) {
                                        [self.delegate getThingsListFinishedWithFailure:error];
                                    }
                                }
                            }];
                       }
                       
                       if (isFailed) {
                           break;
                       }
                       
                       if (thingDict[@"actions"]) {
                           remainingResponses ++;
                           [[SMTWebServiceManager sharedInstance]
                            getAttributesForHref:thingDict[@"actions"]
                            success:^(id response) {
                                NSMutableArray * actions = [NSMutableArray new];
                                for (NSDictionary * actionDict in response[@"items"]) {
                                    SMTThingAction * action = [SMTThingAction new];
                                    [actionDict populateObject:action];
                                    action.name = [actionDict objectForKey:@"type"];
                                    action.executeURL = [actionDict objectForKey:@"execute"];
                                    for (SMTThingActionType * actionType in actionTypes) {
                                        if ([actionType.uuid isEqualToString:action.name]) {
                                            action.actionType = actionType;
                                            break;
                                        }
                                    }
                                    if (action.actionType != nil) {
                                        [actions addObject:action];
                                    }
                                    else {
                                        NSLog(@"Action type %@ in thing %@ does not exist.", action.name, thing.name);
                                    }
                                }
                                thing.actions = actions;
                                remainingResponses --;
                                if (remainingResponses == 0 && !isFailed) {
                                    if ([self.delegate respondsToSelector:@selector(getThingsListFinishedWithSuccess:)]) {
                                        [self.delegate getThingsListFinishedWithSuccess:things];
                                    }
                                }
                            }
                            failure:^(NSError * error) {
                                if (!isFailed) {
                                    isFailed = YES;
                                    if ([self.delegate respondsToSelector:@selector(getThingsListFinishedWithFailure:)]) {
                                        [self.delegate getThingsListFinishedWithFailure:error];
                                    }
                                }
                            }];
                       }
                       [things addObject:thing];
                   }
                   if (remainingResponses == 0 && !isFailed) {
                       if ([self.delegate respondsToSelector:@selector(getThingsListFinishedWithSuccess:)]) {
                           [self.delegate getThingsListFinishedWithSuccess:things];
                       }
                   }
               }
               
               failure:^(NSError * error){
                   if ([self.delegate respondsToSelector:@selector(getThingsListFinishedWithFailure:)]) {
                       [self.delegate getThingsListFinishedWithFailure:error];
                   }
               }];
          } failure:^(NSError * error) {
              if ([self.delegate respondsToSelector:@selector(getThingsListFinishedWithFailure:)]) {
                  [self.delegate getThingsListFinishedWithFailure:error];
              }
          } ];
     } failure:^(NSError * error) {
         if ([self.delegate respondsToSelector:@selector(getThingsListFinishedWithFailure:)]) {
             [self.delegate getThingsListFinishedWithFailure:error];
         }
     } ];
}


- (void)deleteThing:(SMTThing *)thing {
    
    [[SMTWebServiceManager sharedInstance]
     deleteThing:thing.uuid
     success:^(id response) {
         if ([self.delegate respondsToSelector:@selector(deleteThingFinishedWithSuccess:)]) {
             [self.delegate deleteThingFinishedWithSuccess:nil];
         }
     }
     failure:^(NSError * error) {
         if ([self.delegate respondsToSelector:@selector(deleteThingFinishedWithFailure:)]) {
             [self.delegate deleteThingFinishedWithFailure:error];
         }
     }];
}


- (void)addThing:(SMTThing *)thing {
    NSMutableDictionary * thingDict = [NSMutableDictionary new];
    thingDict[@"name"] = thing.name;
    NSMutableArray * actionNames = [NSMutableArray new];
    for (SMTThingAction * action in thing.actions) {
        [actionNames addObject:action.name];
    }
    thingDict[@"actions"] = actionNames;
    NSMutableArray * propertyNames = [NSMutableArray new];
    for (SMTThingProperty * property in thing.properties) {
        [propertyNames addObject:property.name];
    }
    thingDict[@"properties"] = propertyNames;
    
    [[SMTWebServiceManager sharedInstance]
     addThing:thingDict
     
     success:^(id response) {
         if ([self.delegate respondsToSelector:@selector(addThingFinishedWithSuccess:)]) {
             [self.delegate addThingFinishedWithSuccess:nil];
         }
     }
     failure:^(NSError * error) {
         if ([self.delegate respondsToSelector:@selector(addThingFinishedWithFailure:)]) {
             [self.delegate addThingFinishedWithFailure:error];
         }
     }];
}


- (void)editThing:(SMTThing *)thing {
    // TODO: Implementation needed
}

- (void)getPropertyValue:(SMTThingProperty *)property {
    [[SMTWebServiceManager sharedInstance]
     getPropertyValue:property.subscribeURL
     success:^(id response) {
         NSNumber * result;
         if ([response isEqualToString:@"true"]) {
             result = [NSNumber numberWithBool:YES];
         }
         else if ([response isEqualToString:@"false"]) {
             result = [NSNumber numberWithBool:NO];
         }
         else {
             result = [NSNumber numberWithDouble:[response doubleValue]];
         }
         if ([self.delegate respondsToSelector:@selector(getPropertyValueFinishedWithSuccess:forValue:)]) {
             [self.delegate getPropertyValueFinishedWithSuccess:nil forValue:result];
         }
     }
     failure:^(NSError * error) {
         if ([self.delegate respondsToSelector:@selector(getPropertyValueFinishedWithFailure:)]) {
             [self.delegate getPropertyValueFinishedWithFailure:error];
         }
     }];
}


- (void)executeAction:(SMTThingAction *)action {
    
    [[SMTWebServiceManager sharedInstance]
     executeAction:action.executeURL
     success:^(id response) {
         if ([self.delegate respondsToSelector:@selector(executeActionFinishedWithSuccess:)]) {
             [self.delegate executeActionFinishedWithSuccess:nil];
         }
     }
     failure:^(NSError * error) {
         if ([self.delegate respondsToSelector:@selector(executeActionFinishedWithFailure:)]) {
             [self.delegate executeActionFinishedWithFailure:error];
         }
     }];
}

+ (NSArray *)thingPropertyTypes {
    return propertyTypes;
}


+ (NSArray *)thingActionTypes {
    return actionTypes;
}



@end
